package cn.edu.seu.ssny.service.impl;

import cn.edu.seu.ssny.common.utils.DateUtils;
import cn.edu.seu.ssny.dao.IDeviceDataStdDao;
import cn.edu.seu.ssny.entity.DeviceDataStd;
import cn.edu.seu.ssny.enums.ResultCodeEnum;
import cn.edu.seu.ssny.exception.SsnyException;
import cn.edu.seu.ssny.service.IQueryDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class QueryDataServiceImpl implements IQueryDataService {

    @Autowired
    private IDeviceDataStdDao deviceDataStdDao;

    /**
     * 功能描述:
     * <查询deviceIds所指定的所有采集点最近一条数据的总和
     *
     * @param deviceIds
     * @return
     */
    @Override
    public Double getSumOfRecentOneDataOfDevices(List<Integer> deviceIds) {
        if (deviceIds == null || deviceIds.size() == 0) {
            return 0d;
        }
        return deviceDataStdDao.getSumOfRecentOneDataOfDevicesByDeviceInInHourTable(deviceIds);
    }

    /**
     * 功能描述:
     * <查询deviceIds所指定的所有采集点的时段数据之和
     * <example:
     * <deviceIds = [1,2,3]
     * <dates = [20210707000000,20210708000000,...,20210711000000,20210711080909]
     * <timeMode = TimeMode.MODE_DAY
     * <就会返回[1,2,3]采集点在20210707000000,20210708000000,..,20210711000000的时段数据其前后两天零点数据相减(最后一条数据是当前时刻的值与当天0点时刻数值相减)
     * <返回的数据列表长度应该等于输入的时间列表长度减一
     *
     * @param deviceIds
     * @param dates
     * @param timeMode
     * @return
     */
    @Override
    public List<Double> getPeroidSumofDevicesByDateList(List<Integer> deviceIds, List<Date> dates, int timeMode) {
        List<DeviceDataStd> deviceDataStds = this.findAllByDeviceIdsInAndCreateTimeBetweenOrderByCreateTimeASC(deviceIds, dates.get(0), dates.get(dates.size() - 1), timeMode);
        if (deviceDataStds.size() < 2) {
            throw new SsnyException(ResultCodeEnum.ERROR_DATA_NOENOUGH_EXCEPTION);
        }
        /**
         * 1.将某一个时刻的所有设备的数据累加起来
         * 2.两个时刻的累加值相减就是该时段的值
         */
        List<Double> datas = new ArrayList<>();
        double preData = 0;
        double currData = 0;
        //用来表示是不是第一次两个数据的createTime不同，第一次出现不同的时候是不需要做差的
        boolean flag = true;
        for (int i = 0; i < deviceDataStds.size(); i++) {
            if (i == 0) {
                currData += deviceDataStds.get(i).getData();
            } else {
                if (DateUtils.isSameTime(deviceDataStds.get(i - 1).getCreateTime(), deviceDataStds.get(i).getCreateTime())) {
                    currData += deviceDataStds.get(i).getData();
                } else {
                    if (flag) {//第一次出现两个数据创建时间不同
                        flag = false;
                    } else {//非第一次出现两个数据创建时间不同
                        datas.add(currData - preData);
                    }
                    preData = currData;
                    currData = deviceDataStds.get(i).getData();
                }
                if (i == deviceDataStds.size() - 1) {
                    datas.add(currData - preData);
                }
            }
        }
        return datas;
    }

    /**
     * 功能描述:
     * <返回startDate和endDate之间,所有满足timeMode模式的数据和最近的一条数据，并且按照时间ASC
     * <example:
     * <deviceIds = [1,2,3]
     * <startDate = 20210707000000
     * <endDate = 20210722074900
     * <timeMode = TimeMode.DAY_MODE
     * <返回deviceIds在20210707000000、20210708000000、..、20210722000000、最近采集时刻(距离20210722074900)
     *
     * @param deviceIds
     * @param startDate
     * @param endDate
     * @param timeMode
     * @return
     */
    @Override
    public List<DeviceDataStd> findAllByDeviceIdsInAndCreateTimeBetweenOrderByCreateTimeASC(List<Integer> deviceIds, Date startDate, Date endDate, int timeMode) {
        List<DeviceDataStd> list = new ArrayList<>();
        if (deviceIds == null || deviceIds.size() == 0) {
            return list;
        }
        if (timeMode == DateUtils.MODE_HOUR) {
            list = deviceDataStdDao.findAllByDeviceInAndHourOrderByCreateTimeASC(deviceIds, startDate, endDate);
        } else if (timeMode == DateUtils.MODE_DAY) {
            list = deviceDataStdDao.findAllByDeviceInAndDayOrderByCreateTimeASC(deviceIds, startDate, endDate);
        } else if (timeMode == DateUtils.MODE_MONTH) {
            list = deviceDataStdDao.findAllByDeviceInAndMonthOrderByCreateTimeASC(deviceIds, startDate, endDate);
        } else if (timeMode == DateUtils.MODE_YEAR) {
            list = deviceDataStdDao.findAllByDeviceInAndYearOrderByCreateTimeASC(deviceIds, startDate, endDate);
        } else {
            //时间模式选择错误,抛出异常
            throw new SsnyException(ResultCodeEnum.ERROR_TIMEMODE);
        }
        return list;
    }


}
